﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using ModelLayer;
using DAL;
using System.Net.Mail;

namespace BusinessLayer
{
    public class UserB : IFUserB
    {
        public int CreateUser(string fname, string lname, string uname, string email, string pass)
        {
            IFSecurity s = new Security();
            byte[] salt = s.CreateSalt(10);
            byte[] hash = s.GenerateSaltedHash(Encoding.UTF8.GetBytes(pass), salt);

            var udb = new UserDB();

            try
            {
                udb.CreateUser(fname, lname, uname, email, Convert.ToBase64String(hash), Convert.ToBase64String(salt));
            }
            catch (System.Data.SqlClient.SqlException e)
            {
                if (e.Message.Contains("User_uq"))
                {
                    return 2;
                }
                if (e.Message.Contains("UserEmail_uq"))
                {
                    return 3;
                }
                if (e.Message.Contains("Cannot insert the value NULL"))
                {
                    return 4;
                }
                return 5;
            }
            return 1;
        }

        public ModelLayer.User SearchUName(string uname)
        {
            var udb = new UserDB();
            var u = udb.SearchUName(uname);

            return u;
        }

        public ModelLayer.User GetUserById(int id)
        {
            var udb = new UserDB();
            var u = udb.GetUserById(id);

            return u;
        }


        public ModelLayer.User GetUserByEmail(string email)
        {
            var udb = new UserDB();
            var u = udb.GetUserByEmail(email);
            return u;
        }

        public bool AddFriend(string userName, string friendUserName, string tokenId)
        {
            var user = SearchUName(userName);
            int uid = user.UserId;
            var friend = SearchUName(friendUserName);
            int fid = friend.UserId;
            var udb = new UserDB();
            var s = new Security();
            if (s.Authenticate(userName, tokenId))
            {
                udb.AddFriend(uid, fid);
                return true;
            }
            return false;
        }

        public List<ModelLayer.User> SearchUsers(string searchString)
        {
            UserDB userDB = new UserDB();
            try
            {
                MailAddress mailAdress = new MailAddress(searchString);
                return userDB.SearchUsersWithEmail(searchString);
            }
            catch (FormatException)
            {
                return userDB.SearchUsersWithUsername(searchString);
            }
        }

        public string Login(string username, string password)
        {

            var udb = new UserDB();
            IFSecurity sec = new Security();
            IFTokenB token = new TokenB();
            ModelLayer.Token tokenObj = new ModelLayer.Token();
            try
            {
                ModelLayer.User user = udb.SearchUName(username);
                Credential c = udb.Login(user.UserId);
                byte[] loginHash = sec.GenerateSaltedHash(Encoding.UTF8.GetBytes(password), Convert.FromBase64String(c.Salt));
                byte[] hash = Convert.FromBase64String(c.Password);
                Debug.WriteLine("loginHash: " + Convert.ToBase64String(loginHash));
                Debug.WriteLine("hash: " + c.Password);
                if (sec.CompareByteArrays(loginHash, hash))
                {
                    tokenObj = token.FindToken(user.UserId);
                    if (tokenObj != null)
                    {
                        token.DeleteToken(user.UserId);
                    }
                    Debug.WriteLine("creater token");
                    tokenObj = token.CreateToken(user.UserId);
                }
                else return "password_error";
            }
            catch (Exception e)
            {

                return e.Message;
            }
            return tokenObj.TokenId;

        }


        public bool AddToBlacklist(string userName, string blacklistUserName, string tokenId)
        {
            var user = SearchUName(userName);
            int uid = user.UserId;
            var blacklistedUser = SearchUName(blacklistUserName);
            int bid = blacklistedUser.UserId;
            var udb = new UserDB();
            var s = new Security();
            if (s.Authenticate(userName, tokenId))
            {
                udb.AddToBlacklist(uid, bid);
                return true;
            }
            return false;
        }

        public bool RemoveFromBlacklist(string userName, string blacklistUserName, string tokenId)
        {
            var user = SearchUName(userName);
            int uid = user.UserId;
            var blacklistedUser = SearchUName(blacklistUserName);
            int bid = blacklistedUser.UserId;
            var udb = new UserDB();
            var s = new Security();
            if (s.Authenticate(userName, tokenId))
            {
                udb.RemoveFromBlacklist(uid, bid);
                return true;
            }
            return false;
        }


        public List<ModelLayer.User> GetFriends(string uname)
        {
            var udb = new UserDB();
            return udb.GetFriends(uname);
        }
    }
}
